#include "frontaxisnode.h"
#include <osg\CullFace>

namespace VrDataCore
{
	FrontAxisNode::FrontAxisNode(osgViewer::View* view):Drawable(NULL,"FrontAxisNode"),_withView(view)
	{}

	FrontAxisNode::~FrontAxisNode()
	{}

	void FrontAxisNode::createCrossLine(const osg::Vec3& base,float length,const osg::Vec4& colorx,
		const osg::Vec4& colory,const osg::Vec4& colorz)
	{
		_lineX = new osg::Geometry;
		_lineY = new osg::Geometry;
		_lineZ = new osg::Geometry;
		_realnode = new osg::Geode;

		osg::ref_ptr< osg::Vec3Array > _lineXVertexs = new osg::Vec3Array;
		_lineXVertexs->push_back(osg::Vec3(0,0,0));
		_lineXVertexs->push_back(osg::Vec3(length,0.0,0.0));
		osg::ref_ptr< osg::Vec3Array > _lineYVertexs = new osg::Vec3Array;
		_lineYVertexs->push_back(osg::Vec3(0,0,0));
		_lineYVertexs->push_back(osg::Vec3(0.0, length,0.0));
		osg::ref_ptr< osg::Vec3Array > _lineZVertexs = new osg::Vec3Array;
		_lineZVertexs->push_back(osg::Vec3(0,0,0));
		_lineZVertexs->push_back(osg::Vec3(0.0, 0.0, length));

		osg::ref_ptr<osg::Vec4Array> _lineXColors = new osg::Vec4Array ;
		_lineXColors->push_back( colorx ) ;
		osg::ref_ptr<osg::Vec4Array> _lineYColors = new osg::Vec4Array ;
		_lineYColors->push_back( colory ) ;
		osg::ref_ptr<osg::Vec4Array> _lineZColors = new osg::Vec4Array ;
		_lineZColors->push_back( colorz ) ;

		_lineX->setVertexArray( _lineXVertexs ) ;
		_lineX->setColorArray( _lineXColors ) ;
		_lineX->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET);
		_lineX->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2));
		_lineY->setVertexArray( _lineYVertexs ) ;
		_lineY->setColorArray( _lineYColors ) ;
		_lineY->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET);
		_lineY->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2));
		_lineZ->setVertexArray( _lineZVertexs ) ;
		_lineZ->setColorArray( _lineZColors ) ;
		_lineZ->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET);
		_lineZ->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2));

		_realnode->addDrawable(_lineX);
		_realnode->addDrawable(_lineY);
		_realnode->addDrawable(_lineZ);
		createCoordinateText(osg::Vec3(length*1.1f,0.0,0.0),osg::Vec3(0.0, length*1.1f,0.0)
			,osg::Vec3(0.0,0.0,length*1.1f),colorx,colory,colorz);
		_transformNode = new osg::MatrixTransform ;
		_transformNode->addChild(_realnode);
		_baseTransMatrix.makeTranslate(base);
		_transformNode->setMatrix(_baseTransMatrix);
		_transformNode->addUpdateCallback(new AxisUpdateCallback(this));
	}

	void FrontAxisNode::createCoordinateText(const osg::Vec3& xpos,const osg::Vec3& ypos,const osg::Vec3& zpos,
		const osg::Vec4& colorx,const osg::Vec4& colory,const osg::Vec4& colorz)
	{
		_textgeoX = new osgText::Text;
		_textgeoY = new osgText::Text;
		_textgeoZ = new osgText::Text;
		std::string labelX = "X" ;
		std::string labelY = "Y" ;
		std::string labelZ = "Z" ;
		osg::Vec4 color(0.0,0.0,0.0,1.0) ;
		osg::StateSet *ss = new osg::StateSet;
		osg::CullFace *cf = new osg::CullFace(osg::CullFace::FRONT_AND_BACK);
		ss->setAttributeAndModes( cf, osg::StateAttribute::OFF );
		//ss->setMode( GL_CULL_FACE, osg::StateAttribute::OFF ) ;

		_textgeoX->setPosition(xpos);
		_textgeoX->setColor( colorx ) ;
		_textgeoX->setCharacterSize( 12.0 ) ;
		_textgeoX->setText(labelX.c_str());
		_textgeoX->setAxisAlignment( osgText::Text::SCREEN ) ;
		_textgeoX->setStateSet( ss ) ;

		_textgeoY->setPosition(ypos);
		_textgeoY->setColor( colory ) ;
		_textgeoY->setCharacterSize( 12.0 ) ;
		_textgeoY->setText(labelY.c_str());
		_textgeoY->setAxisAlignment( osgText::Text::SCREEN ) ;

		_textgeoZ->setPosition(zpos);
		_textgeoZ->setColor( colorz ) ;
		_textgeoZ->setCharacterSize( 12.0 ) ;
		_textgeoZ->setText(labelZ.c_str());
		_textgeoZ->setAxisAlignment( osgText::Text::SCREEN ) ;

		if( _realnode.valid() )
		{
			osg::Vec3 pos(0.0,0.0,0.0) ;
			_realnode->addDrawable( _textgeoX ) ;
			_realnode->addDrawable( _textgeoY  ) ;
			_realnode->addDrawable( _textgeoZ  ) ;
		}
	}

	void FrontAxisNode::update()
	{
		if(_withView!=NULL)
		{
			osg::Matrixd mx = _withView->getCameraManipulator()->getInverseMatrix();
			osg::Matrixd newmx(mx.getRotate());
			newmx = newmx*_baseTransMatrix;
			_transformNode->setMatrix(newmx);
		}
	}

	osg::Node* FrontAxisNode::getOSGNode()
	{
		return _transformNode;
	}

	const osg::Node* FrontAxisNode::getOSGNode() const
	{
		return _transformNode;
	}
}